#include <fmod.hpp>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include "jni.h"


#define LOG_E(FORMAT, ...) ((void)__android_log_print(ANDROID_LOG_ERROR, "test_fmod", FORMAT, __VA_ARGS__))

using namespace FMOD;

#define SPEED_UP 1
#define SWELL_TONE 2
#define BASS_TONE 3
#define ECHO 4


FMOD::Channel *channel = 0;

void stopPlaying();

extern "C"
JNIEXPORT void JNICALL Java_com_tys_fmod_AudioHandle_playSound
        (JNIEnv *env, jclass type, jstring path_, jint mode) {
    const char *path = env->GetStringUTFChars(path_, 0);
    FMOD::System *sys = 0;
    FMOD_RESULT result;
    Sound *sound = NULL;
    DSP *dsp = 0;
    try {
        stopPlaying();
        //Create a System object and initialize
        result = System_Create(&sys);
        ERRCHECK(result);
        result = sys->init(32, FMOD_INIT_NORMAL, 0);
        ERRCHECK(result);
        result = sys->createSound(path, FMOD_DEFAULT, 0, &sound);
        ERRCHECK(result);
        result = sound->setMode(FMOD_LOOP_OFF);//drumloop.wav has embedded loop points which automatically makes looping turn on
        ERRCHECK(result); //so turn it off here.  We could have also just put FMOD_LOOP_OFF in the above CreateSound call
        result = sys->playSound(sound, 0, false, &channel);
        ERRCHECK(result);
        switch (mode){
            case SPEED_UP:
                float frequency;
                channel->getFrequency(&frequency);
                frequency = frequency * 1.8f;
                channel->setFrequency(frequency);
                break;
            case BASS_TONE:
                sys->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 0.8);
                channel->addDSP(0, dsp);
                break;
            case SWELL_TONE:
                sys->createDSPByType(FMOD_DSP_TYPE_PITCHSHIFT, &dsp);
                dsp->setParameterFloat(FMOD_DSP_PITCHSHIFT_PITCH, 1.8f);
                channel->addDSP(0, dsp);
                break;
            case ECHO:
                sys->createDSPByType(FMOD_DSP_TYPE_ECHO, &dsp);
                dsp->setParameterFloat(FMOD_DSP_ECHO_DELAY, 300);
                dsp->setParameterFloat(FMOD_DSP_ECHO_FEEDBACK, 20);
                channel->addDSP(0, dsp);
                break;
            default:
                break;
        }
        sys->update();
        bool playing = true;
        if (channel) {
            while (playing) {
                channel->isPlaying(&playing);
                usleep(1000 * 1000);
            }
        }
    } catch (...) {
        goto error;
    }
    error:
    if(dsp){
        channel->removeDSP(dsp);
    }
    sound->release();
    sys->close();
    sys->release();
    env->ReleaseStringUTFChars(path_, path);
}


void stopPlaying() {
    bool playing = false;
    if(channel){
        channel->isPlaying(&playing);
        if(playing)
            channel->stop();
    }
}

